﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using C4F.VistaP2P.Common;

namespace C4F.VistaP2P.Win.Media
{
    /// <summary>
    /// Use this control with the NetworkManager or NetworkManager(ADV) to share audio or video
    /// </summary>
    [Description("Use this control with the NetworkManager to share audio or video"),
     ToolboxBitmap(typeof(resfinder), "C4F_P2PWinformControls.c4f.bmp"),
    Designer(typeof(MediaDesigner))] //this designer attribute enables us to have smart tags on the control
    public partial class MediaControl : UserControl
    {
        /// <summary>
        /// Constructor that just shows initiales the media control form.
        /// </summary>
        public MediaControl()
        {
            InitializeComponent();           
        }

#region public methods and events to use when completely overriding this control
        /// <summary>
        /// register for status changed events on the control.
        /// </summary>
        public event EventHandler<StatusChangedEventArgs> StatusChanged;      

#endregion

        /// <summary>
        /// Start playing the media file found at the url location in the string passed in.
        /// </summary>
        /// <param name="play">the url to play</param>
        public void StartPlay(string play)
        {
           this.axWindowsMediaPlayer.URL = play;          
        }
        
        /// <summary>
        /// The NetworkManager control subscribes to this event so it can send a file to the mesh.
        /// </summary>
        internal event EventHandler<SendStreamEventArgs> SendingStream;

        /// <summary>
        /// Displays a form to send a media file.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _SendButton_Click(object sender, EventArgs e)
        {
            if (SendingStream != null)
            {
                Microsoft.Win32.OpenFileDialog ofd;
                ofd = new Microsoft.Win32.OpenFileDialog();
                ofd.FileName = "";               
                ofd.Filter = "(*.wmv)|*.wmv|(*.wma)|*.wma|(*.mp3)|*.mp3|All Files (*.*)|*.*";
                ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                ofd.RestoreDirectory = true;
                ofd.Title = "Select a Video/Audio source";

                //check return value, but how in wpf?
                bool ok = (bool)ofd.ShowDialog();
                if (ok)
                {
                    SendingStream(this, new SendStreamEventArgs(ofd.FileName));
                }
            }
        }

        /// <summary>
        /// The NetworkManager control subscribes to this event so it can send a file to the mesh.
        /// </summary>
        internal event EventHandler CancelStream;

        /// <summary>
        /// Cancels the stream.
        /// </summary>
        /// <param name="sender">unused</param>
        /// <param name="e">unused</param>
        private void _CancelButton_Click(object sender, EventArgs e)
        {
            if (CancelStream != null)
            {
                CancelStream(this, new EventArgs());
            }
        }

        /// <summary>
        /// Used to cause the function SetStatusMessage to be called on the controls thread
        /// </summary>
        /// <param name="msg">the status message to stay</param>
        private delegate void SetStausMessageHandler(string msg);
        internal void SetStatusMessage(string msg)
        {
            if (tbStatusLog.InvokeRequired)
            {
                tbStatusLog.Invoke(new SetStausMessageHandler(SetStatusMessage), msg);
            }
            else
            {
                this.tbStatusLog.Text += msg + "\r\n";
                tbStatusLog.SelectAll();
                tbStatusLog.ScrollToCaret();
            }            
        }

        
        /// <summary>
        /// A place to store the custom button if assigned.
        /// </summary>
        private Button mSendButton = null;

        /// <summary>
        /// The SendFileButton Button property.  Set this to another button if you wish to customize the control some.
        /// The Attributes (Description and Category) expose the property on the Winforms design surface.
        /// The get method returns the custom button if set (mSendFileButton), or the default one (btnSendFile) if one
        /// is not set.
        /// <value></value>
        /// </summary>
        [
           Description(""),
           Category("P2P/controls")
        ]
        public Button SendButton
        {
            get
            {
                if (mSendButton == null)
                    return btnSend;
                else
                    return mSendButton;
            }
            set
            {
                //if we previously registered for a button, unregister for it.
                if (mSendButton != null)
                {
                    mSendButton.Click -= new EventHandler(_SendButton_Click);
                }

                mSendButton = value;
                if (value != null)
                {
                    //unregister for the default event
                    btnSend.Visible = false;
                    btnSend.Click -= new EventHandler(_SendButton_Click);

                    //register for the new controls event
                    mSendButton = value;
                    mSendButton.Click += new EventHandler(_SendButton_Click);
                }
                else
                {
                    btnSend.Visible = true;
                    btnSend.Click += new EventHandler(_SendButton_Click);
                    Show();
                }
            }
        }

        
        /// <summary>
        /// A place to store the custom button if assigned.
        /// </summary>
        private Button mCancelButton = null;

        /// <summary>
        /// The SendFileButton Button property.  Set this to another button if you wish to customize the control some.
        /// The Attributes (Description and Category) expose the property on the Winforms design surface.
        /// The get method returns the custom button if set (mSendFileButton), or the default one (btnSendFile) if one
        /// is not set.
        /// <value></value>
        /// </summary>
        [
           Description(""),
           Category("P2P/controls")
        ]
        public Button CancelButton
        {
            get
            {
                if (mCancelButton == null)
                    return btnCancel;
                else
                    return mCancelButton;
            }
            set
            {
                //if we previously registered for a button, unregister for it.
                if (mCancelButton != null)
                {
                    mCancelButton.Click -= new EventHandler(_CancelButton_Click);
                }

                mCancelButton = value;
                if (value != null)
                {
                    //unregister for the default event
                    btnCancel.Visible = false;
                    btnCancel.Click -= new EventHandler(_CancelButton_Click);

                    //register for the new controls event
                    mCancelButton = value;
                    mCancelButton.Click += new EventHandler(_CancelButton_Click);
                }
                else
                {
                    btnCancel.Visible = true;
                    btnCancel.Click += new EventHandler(_CancelButton_Click);
                    Show();
                }
            }
        }

        /// <summary>
        /// a place to store the custom status log.
        /// </summary>
        private TextBox mStatusLog = null;
        
        /// <summary>
        /// The StatusLog TextBox property.  Set this to another textbox if you wish to have this control updated with 
        /// the status log.
        /// The Attributes (Description and Category) expose the property on the Winforms design surface.
        /// The get method returns the custom textbox if set (mStatusLog), or the default one (tbStatus) if one
        /// is not set.
        /// <value></value>
        /// </summary>
        [
           Description(""),
           Category("P2P/controls")
        ]
        public TextBox StatusLog
        {
            get
            {
                if (mStatusLog == null)
                    return tbStatusLog;
                else
                    return mStatusLog;
            }
            set
            {
                mStatusLog = value;
                if (value != null)
                {
                    tbStatusLog.Visible = false;                    
                }
                else
                {
                    this.Show();
                    tbStatusLog.Visible = true;
                }
            }
        }

        
        /// <summary>
        /// a place to store the custom status log.
        /// </summary>
        private Label mFirstLineValue = null;

        /// <summary>
        /// The FirstLineValue TextBox property.  Set this to another label if you wish to have this control updated with 
        /// the first line value.
        /// The Attributes (Description and Category) expose the property on the Winforms design surface.
        /// The get method returns the custom textbox if set (mFirstLineValue), or the default one (lblFirstLineValue) if one
        /// is not set.
        /// <value></value>
        /// </summary>
        [
           Description(""),
           Category("P2P/controls")
        ]
        public Label FirstLineValue
        {
            get
            {
                if (mFirstLineValue == null)
                    return lblFirstLineValue;
                else
                    return mFirstLineValue;
            }
            set
            {
                mFirstLineValue = value;
                if (value != null)
                {
                    lblFirstLineValue.Visible = false;
                }
                else
                {
                    this.Show();
                    lblFirstLineValue.Visible = true;
                }
            }
        }

        
        /// <summary>
        /// a place to store the second line value. 
        /// </summary>
        private Label mSecondLineValue = null;
        
        /// <summary>
        /// The SecondLineValue property.  Set this to another label if you wish to have this control updated with 
        /// the second line value.
        /// The Attributes (Description and Category) expose the property on the Winforms design surface.
        /// The get method returns the custom label if set (mSecondLineValue), or the default one (tbStatus) if one
        /// is not set.
        /// <value></value>
        /// </summary>
        [
           Description(""),
           Category("P2P/controls")
        ]
        public Label SecondLineValue
        {
            get
            {
                if (mSecondLineValue == null)
                    return lblSecondLineValue;
                else
                    return mSecondLineValue;
            }
            set
            {
                mSecondLineValue = value;
                if (value != null)
                {
                    lblSecondLineValue.Visible = false;
                }
                else
                {
                    this.Show();
                    lblSecondLineValue.Visible = true;
                }
            }
        }

        
        /// <summary>
        /// a place to store the third line value.
        /// </summary>        
        private Label mThirdLineValue = null;
        
        /// <summary>
        /// The third line value label property.  Set this to another label if you wish to have this control updated with 
        /// the meta data.
        /// The Attributes (Description and Category) expose the property on the Winforms design surface.
        /// The get method returns the custom textbox if set (mThirdLineValue), or the default one (lblThirdLineValue) if one
        /// is not set.
        /// <value></value>
        /// </summary>
        [
           Description(""),
           Category("P2P/controls")
        ]
        public Label ThirdLineValue
        {
            get
            {
                if (mThirdLineValue == null)
                    return lblThirdLineValue;
                else
                    return mThirdLineValue;
            }
            set
            {
                mThirdLineValue = value;
                if (value != null)
                {
                    lblThirdLineValue.Visible = false;
                }
                else
                {
                    this.Show();
                    lblThirdLineValue.Visible = true;
                }
            }
        }


        
        /// <summary>
        /// a place to store the First Line Label. 
        /// </summary>
        private Label mFirstLineLabel = null;

        /// <summary>
        /// Gets or sets the First Line Label,usually has the values Tile
        /// </summary>
        [
           Description(""),
           Category("P2P/controls")
        ]
        public Label FirstLineLabel
        {
            get
            {
                if (mFirstLineLabel == null)
                    return lblFirstLineLabel;
                else
                    return mFirstLineLabel;
            }
            set
            {
                mFirstLineLabel = value;
                if (value != null)
                {
                    lblFirstLineLabel.Visible = false;
                }
                else
                {
                    this.Show();
                    lblFirstLineLabel.Visible = true;
                }
            }
        }


        /// <summary>
        /// A place to store the SecondLineLabel
        /// </summary>
        private Label mSecondLineLabel = null;
        
        /// <summary>
        /// Gets or sets the SecondLineLabel
        /// </summary>
        [
           Description(""),
           Category("P2P/controls")
        ]               
        public Label SecondLineLabel
        {
            get
            {
                if (mSecondLineLabel == null)
                    return lblSecondLineLabel;
                else
                    return mSecondLineLabel;
            }
            set
            {
                mSecondLineLabel = value;
                if (value != null)
                {
                    lblSecondLineLabel.Visible = false;
                }
                else
                {
                    this.Show();
                    lblSecondLineLabel.Visible = true;
                }
            }
        }

        
        /// <summary>
        /// a place to store the custom status log.
        /// </summary>
        private Label mThirdLineLabel = null;

        /// <summary>
        /// Gets or sets the third line label. This usually has the value "Artist" on audio files
        /// </summary>
        [
           Description(""),
           Category("P2P/controls")
        ]
        public Label ThirdLineLabel
        {
            get
            {
                if (mThirdLineLabel == null)
                    return lblThirdLineLabel;
                else
                    return mThirdLineLabel;
            }
            set
            {
                mThirdLineLabel = value;
                if (value != null)
                {
                    lblThirdLineLabel.Visible = false;
                }
                else
                {
                    this.Show();
                    lblThirdLineLabel.Visible = true;
                }
            }
        }

        
        /// <summary>
        /// a place to store the external media player assigned.
        /// </summary>
        private AxWMPLib.AxWindowsMediaPlayer mMediaPlayer = null;

        /// <summary>
        /// The MediaPlayer property.  Set this to another media player if you wish to have this control updated.
        /// The Attributes (Description and Category) expose the property on the Winforms design surface.
        /// The get method returns the custom textbox if set (mStatusLog), or the default one (tbStatus) if one
        /// is not set.
        /// <value></value>
        /// </summary>
        [
           Description(""),
           Category("P2P/controls")
        ]
        public AxWMPLib.AxWindowsMediaPlayer MediaPlayer
        {
            get
            {
                if (mMediaPlayer == null)
                    return axWindowsMediaPlayer;
                else
                    return mMediaPlayer;
            }
            set
            {
                mMediaPlayer = value;
                if (value != null)
                {
                    axWindowsMediaPlayer.Visible = false;
                }
                else
                {
                    this.Show();
                    axWindowsMediaPlayer.Visible = true;
                }
            }
        }



        /// <summary>
        /// _StatusChangedHandler delegate used to ensure that the control is only changed by the thread that created it.
        /// look for crossthreading issues for more information.
        /// </summary>
        /// <param name="userName">The username of the NetworkManager this Media control is connected to</param>
        /// <param name="e">The Status changed Event</param>
        private delegate void _SetStatusChangedHandler(string userName, StatusChangedEventArgs e);
        internal void SetStatusChanged(string userName, C4F.VistaP2P.Common.StatusChangedEventArgs e)
        {
            if (SendButton.InvokeRequired)
            {
                //invoke the call on the controls thread.
                SendButton.Invoke(new _SetStatusChangedHandler(SetStatusChanged), new object[] { userName, e });
            }
            else
            {
                //we're on the controls thread...change it if necessary
                if (userName == e.Member && e.NewNodeJoined)
                {
                    SendButton.Enabled = true;
                    CancelButton.Enabled = true;
                }

                if (userName == e.Member && e.NodeLeft)
                {
                    SendButton.Enabled = false;
                    CancelButton.Enabled = false;
                }

                //raise the status changed event for anyone listening.
                if (null != StatusChanged)
                {
                    StatusChanged(userName, e);
                }
            }
        }
        
        /// <summary>
        /// Shadow the visible property for smart tag..
        /// </summary>
        internal bool ShadowVisible
        {
            get
            {
                return Visible;
            }
            set
            {
                Visible = value;
            }
        }

    }
}
